package com.chenfwind.shiro;

import java.util.List;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.chenfwind.domain.User;
import com.chenfwind.service.UserService;

@Service("realm")
public class Realm extends AuthorizingRealm {

	@Autowired
	private UserService userService;
	/** 
     * 为当前登录的Subject授予角色和权限 
     * @see  经测试:本例中该方法的调用时机为需授权资源被访问时 
     * @see  经测试:并且每次访问需授权资源时都会执行该方法中的逻辑,这表明本例中默认并未启用AuthorizationCache 
     * @see  个人感觉若使用了Spring3.1开始提供的ConcurrentMapCache支持,则可灵活决定是否启用AuthorizationCache 
     * @see  比如说这里从数据库获取权限信息时,先去访问Spring3.1提供的缓存,而不使用Shior提供的AuthorizationCache 
     */  
	@Override
	protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection pc) {
		// TODO Auto-generated method stub
		System.out.println("调用授权模式");
		String account = (String) pc.fromRealm(getName()).iterator().next();
		if(account != null){
			List<String> pers =userService.getPermissionByAccount(account);
			if(pers != null && !pers.isEmpty()){
				SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
				for(String each : pers){
					info.addStringPermission(each);
				}
				return info;
			}
		}
		return null;
	}

	  /** 
	   * 获取认证信息
     * 验证当前登录的Subject 
     * @see  经测试:本例中该方法的调用时机为LoginController.login()方法中执行Subject.login()时 
     */  
	@Override
	protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken at) throws AuthenticationException {
		// TODO Auto-generated method stub
		System.out.println("验证当前登录账号");
		UsernamePasswordToken token = (UsernamePasswordToken) at;
		//通过表单接收的用户名
		String account = token.getUsername();
		if(account != null && !"".equals(account)){
			User user = userService.getUserByAccount(account);
			if(user != null){
				System.out.println("user:" + user);
				return new SimpleAuthenticationInfo(user.getAccount(), user.getPassword(), getName());
			}
			
		}
		return null;
	}

	/** 
     * 将一些数据放到ShiroSession中,以便于其它地方使用 
     * @see  比如Controller,使用时直接用HttpSession.getAttribute(key)就可以取到 
     */  
//    private void setSession(Object key, Object value){  
//        Subject currentUser = SecurityUtils.getSubject();  
//        if(null != currentUser){  
//            Session session = currentUser.getSession();  
//            System.out.println("Session默认超时时间为[" + session.getTimeout() + "]毫秒");  
//            if(null != session){  
//                session.setAttribute(key, value);  
//            }  
//        }  
//    }  
}
